package com.sinosoft.hydra.um.services;

import com.sinosoft.hydra.um.condition.SearchProcessTemplateCondition;
import com.sinosoft.hydra.um.constant.BaseConstant;
import com.sinosoft.hydra.um.domain.model.LabGroup;
import com.sinosoft.hydra.um.domain.permission.TProcessAttribute;
import com.sinosoft.hydra.um.domain.permission.TProcessParameter;
import com.sinosoft.hydra.um.domain.permission.TProcessRecord;
import com.sinosoft.hydra.um.domain.permission.TProcessTemplate;
import cn.com.sinux.spring.exception.BusinessException;
import com.sinosoft.hydra.um.helper.AuthContextHelper;
import com.sinosoft.hydra.um.repositories.TProcessAttributeDAO;
import com.sinosoft.hydra.um.repositories.TProcessParameterDAO;
import com.sinosoft.hydra.um.repositories.TProcessRecordDAO;
import com.sinosoft.hydra.um.repositories.TProcessTemplateDAO;
import cn.com.sinux.spring.utils.CodeUtils;
import cn.com.sinux.spring.utils.SpecificationHelper;
import cn.com.sinux.spring.utils.ValidatorUtils;;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.util.*;

/**
 * Created by Administrator on 2016/6/16.
 */
@Service
public class ProcessManageService {

    @Autowired
    private TProcessTemplateDAO processTemplateDAO;

    @Autowired
    private TProcessAttributeDAO processAttributeDAO;

    /**
     * 查找所有实验
     *
     * @return
     */
    public List<LabGroup> findAllProcess() {
        SearchProcessTemplateCondition searchProcessTemplateCondition = new SearchProcessTemplateCondition();
        searchProcessTemplateCondition.setUseAble(BaseConstant.INTEGER_TRUE);
        List<TProcessTemplate> processTemplates = findAll(searchProcessTemplateCondition, null).getContent();
        Map<String, List<TProcessTemplate>> group = new TreeMap<String, List<TProcessTemplate>>();
        for (TProcessTemplate processTemplate : processTemplates) {
            List<TProcessTemplate> list = group.get(processTemplate.getModule().getDirValue());
            if (list == null) {
                list = new ArrayList<TProcessTemplate>();
            }
            list.add(processTemplate);
            group.put(processTemplate.getModule().getDirValue(), list);
        }
        List<LabGroup> groups = new ArrayList<LabGroup>(group.size());
        for (Map.Entry<String, List<TProcessTemplate>> pa : group.entrySet()) {
            LabGroup labGroup = new LabGroup();
            labGroup.setModuleName(pa.getKey());
            labGroup.setProcessTemplates(pa.getValue());
            if (ValidatorUtils.isArrayNotEmpty(pa.getValue())) {
                labGroup.setOrder(pa.getValue().get(0).getModule().getDirOrder());
            }
            groups.add(labGroup);
        }
        Collections.sort(groups, new Comparator<LabGroup>() {

            public int compare(LabGroup labGroup, LabGroup labGroup2) {
                return labGroup2.getOrder().compareTo(labGroup.getOrder());
            }
        });
        return groups;
    }

    /**
     * 保存工艺模板
     *
     * @param processTemplate
     */
    @Transactional
    public TProcessTemplate addProcess(TProcessTemplate processTemplate) {
        SearchProcessTemplateCondition searchProcessTemplateCondition = new SearchProcessTemplateCondition();
        searchProcessTemplateCondition.setProcessName(processTemplate.getProcessName());
        if (processTemplateDAO.count(buildSpecification(searchProcessTemplateCondition)) > 0) {
            throw new BusinessException("#该名字的模板已经存在，请重新填写");
        }
        if (ValidatorUtils.isArrayEmpty(processTemplate.gettProcessAttributes())) {
            throw new BusinessException("#创建的模板至少需要一个参数");
        }
        processTemplate.setCreateTime(new Date());
        if (BaseConstant.INTEGER_TRUE.equals(processTemplate.getUseDevice())) {
            if (processTemplate.getDevice() == null || StringUtils.isBlank(processTemplate.getDevice().getId())) {
                throw new BusinessException("至少选择一个程控设备");
            }
        }
        List<TProcessAttribute> processAttributes = processTemplate.gettProcessAttributes();
        processTemplate.settProcessAttributes(null);
        processTemplateDAO.save(processTemplate);
        int seq = 1;
        for (TProcessAttribute processAttribute : processAttributes) {
            if (processAttribute.getUseDevice() == null) {
                processAttribute.setUseDevice(BaseConstant.INTEGER_FALSE);
            }
            if (processAttribute.getSearchAble() == null) {
                processAttribute.setSearchAble(BaseConstant.INTEGER_FALSE);
            }
            if(BaseConstant.FiledType.FIELD_TYPE_DIRECTORY.name().equals(processAttribute.getFieldType())){
                processAttribute.setUnit("");
            }
            if(processAttribute.getNotNull() == null){
                processAttribute.setNotNull(BaseConstant.INTEGER_FALSE);
            }
            processAttribute.setUseBale(BaseConstant.INTEGER_TRUE);
            processAttribute.setOrderNo(seq);
            processAttribute.settProcessTemplate(processTemplate);
            seq++;
        }
        processAttributeDAO.save(processAttributes);
        return processTemplate;
    }

    /**
     * 保存工艺模板
     *
     * @param processTemplate
     */
    @Transactional
    public TProcessTemplate updateProcess(TProcessTemplate processTemplate) {
        TProcessTemplate db = findOne(processTemplate.getId());
        if (db == null) {
            throw new BusinessException("#不存在的数据，不能保存");
        }
        SearchProcessTemplateCondition searchProcessTemplateCondition = new SearchProcessTemplateCondition();
        searchProcessTemplateCondition.setProcessName(processTemplate.getProcessName());
        if (!db.getProcessName().equals(processTemplate.getProcessName()) &&
                processTemplateDAO.count(buildSpecification(searchProcessTemplateCondition)) > 0) {
            throw new BusinessException("#该名字的模板已经存在，请重新填写");
        }
        if (ValidatorUtils.isArrayEmpty(processTemplate.gettProcessAttributes())) {
            throw new BusinessException("#创建的模板至少需要一个参数");
        }
        processTemplate.setCreateTime(db.getCreateTime());
        processTemplate.setUpdateTime(new Date());
        processTemplate.setCreateUser(db.getCreateUser());
        if (BaseConstant.INTEGER_TRUE.equals(processTemplate.getUseDevice())) {
            if (processTemplate.getDevice() == null || StringUtils.isBlank(processTemplate.getDevice().getId())) {
                throw new BusinessException("至少选择一个程控设备");
            }
        }
        List<TProcessAttribute> processAttributes = processTemplate.gettProcessAttributes();
        processTemplate.settProcessAttributes(null);
        processTemplate.setRecords(db.getRecords());
        processTemplateDAO.save(processTemplate);
        //比对现有数据，如果之前存在，现在不存在的则
        int seq = 1;
        for (TProcessAttribute processAttribute : processAttributes) {
            if (processAttribute.getUseDevice() == null) {
                processAttribute.setUseDevice(BaseConstant.INTEGER_FALSE);
            }
            if (processAttribute.getSearchAble() == null) {
                processAttribute.setSearchAble(BaseConstant.INTEGER_FALSE);
            }
            if (processAttribute.getUseBale() == null) {
                processAttribute.setUseBale(BaseConstant.INTEGER_TRUE);
            }
            if (processAttribute.getNotNull() == null) {
                processAttribute.setNotNull(BaseConstant.INTEGER_FALSE);
            }
            if(BaseConstant.FiledType.FIELD_TYPE_DIRECTORY.name().equals(processAttribute.getFieldType())){
                processAttribute.setUnit("");
            }
            if (StringUtils.isBlank(processAttribute.getFieldName())) {
                TProcessAttribute attribute = processAttributeDAO.findOne(processAttribute.getId());
                processAttribute.setFieldName(attribute == null ? "NVL" : attribute.getFieldName());
            }
            processAttribute.setOrderNo(seq);
            processAttribute.settProcessTemplate(processTemplate);
            seq++;
        }
        processAttributeDAO.save(processAttributes);
        return processTemplate;
    }

    /**
     * 查询单个模板
     *
     * @param id
     * @return
     */
    public TProcessTemplate findOne(String id) {
        TProcessTemplate processTemplate = StringUtils.isBlank(id)
                ? null
                : processTemplateDAO.findOne(id);
        if (processTemplate == null || ValidatorUtils.isArrayEmpty(processTemplate.gettProcessAttributes())) {
            return processTemplate;
        }
        for (TProcessAttribute processAttribute : processTemplate.gettProcessAttributes()) {
            processAttribute.setFieldTypeName(BaseConstant.FiledType.valueOf(processAttribute.getFieldType()).getValue());
        }
        Collections.sort(processTemplate.gettProcessAttributes(), new Comparator<TProcessAttribute>() {

            public int compare(TProcessAttribute tProcessAttribute, TProcessAttribute tProcessAttribute2) {
                return tProcessAttribute.getOrderNo().compareTo(tProcessAttribute2.getOrderNo());
            }
        });
        return processTemplate;
    }

    /**
     * 查找允许搜索的参数
     * @param id
     * @return
     */
    public List<TProcessAttribute> findSearchAttribute(String id) {
        TProcessTemplate processTemplate = findOne(id);
        if(!processTemplate.isSearchAble()){
            return Collections.emptyList();
        }
        List<TProcessAttribute> attributes = new ArrayList<TProcessAttribute>();
        for(TProcessAttribute processAttribute : processTemplate.gettProcessAttributes()){
            if(BaseConstant.INTEGER_TRUE.equals(processAttribute.getSearchAble())){
                attributes.add(processAttribute);
            }
        }
        return attributes;
    }

    /**
     * 查询所有模板
     *
     * @param searchProcessTemplateCondition
     * @param pageable
     * @return
     */
    public Page<TProcessTemplate> findAll(final SearchProcessTemplateCondition searchProcessTemplateCondition, Pageable pageable) {
        return processTemplateDAO.findAll(buildSpecification(searchProcessTemplateCondition), pageable);
    }

    private Specification<TProcessTemplate> buildSpecification(final SearchProcessTemplateCondition searchProcessTemplateCondition) {
        Specification<TProcessTemplate> specification = SpecificationHelper.buildSpecification(new SpecificationHelper.SpecificationBuilder<TProcessTemplate>() {

            public void fillParam(Root<TProcessTemplate> root, CriteriaBuilder cb, List<Predicate> list) {
                if (StringUtils.isNotBlank(searchProcessTemplateCondition.getProcessName())) {
                    list.add(searchProcessTemplateCondition.isLikeName()
                            ? cb.like(root.get("processName").as(String.class), "%" + searchProcessTemplateCondition.getProcessName() + "%")
                            : cb.equal(root.get("processName").as(String.class), searchProcessTemplateCondition.getProcessName()));
                }
                if (searchProcessTemplateCondition.getUseAble() != null) {
                    list.add(cb.equal(root.get("useAble").as(Integer.class), searchProcessTemplateCondition.getUseAble()));
                }
                if (searchProcessTemplateCondition.getModule() != null && StringUtils.isNotBlank(searchProcessTemplateCondition.getModule().getId())) {
                    list.add(cb.equal(root.get("module").get("id").as(String.class), searchProcessTemplateCondition.getModule().getId()));
                }
            }
        });
        return specification;
    }
}
